/**
  ******************************************************************************
  * @file    main.c
  * @author  MCU Application Team
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2023 Puya Semiconductor Co.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by Puya under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "segment_LED.h"
#include "redstone.h"
#include "redstone_repeater.h"

/* Private define ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

__IO uint16_t             ADC_converted_data[5];
__IO uint8_t              flag_conversion_complete = 0;

ADC_HandleTypeDef hadc;

struct redstone_repeater_stu myRS_repeater = {
    .rs_back = {
        .get_millivolt = myRS_get_mv_back,
    },
    .rs_left = {
        .get_millivolt = myRS_get_mv_left,
    },
    .rs_right = {
        .get_millivolt = myRS_get_mv_right,
    },

    .pin_list = {
        [RP_PIN_OUTPUT_LED] = {
            .port = GPIOA,
            .pin = GPIO_PIN_5,
        },
        [RP_PIN_OUTPUT] = {
            .port = GPIOA,
            .pin = GPIO_PIN_7,
        },
        [RP_PIN_LATCH_LED] = {
            .port = GPIOB,
            .pin = GPIO_PIN_2,
        },

        [RP_PIN_GEAR1] = {
            .port = GPIOB,
            .pin = GPIO_PIN_4,
        },
        [RP_PIN_GEAR2] = {
            .port = GPIOB,
            .pin = GPIO_PIN_3,
        },
        [RP_PIN_GEAR3] = {
            .port = GPIOB,
            .pin = GPIO_PIN_0,
        },
        [RP_PIN_GEAR4] = {
            .port = GPIOA,
            .pin = GPIO_PIN_0,
        },
    },

    .pin_init = myRP_pin_init,
    .write_pin = myRP_write_pin,
    .read_pin = myRP_read_pin,
};

/* Private user code ---------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void APP_SystemClockConfig(void);
void myADC_init(void);

/**
  * @brief  Main program.
  * @retval int
  */
int main(void)
{
    /* Reset of all peripherals, Initializes the Systick. */
    HAL_Init();
    
    /* System clock configuration */
    APP_SystemClockConfig();

    SEGGER_RTT_Init();

    myADC_init();
    if(RS_repeater_init(&myRS_repeater) != 0){
        while(1){
            LOG_STR(PRINT_ERROR"Rrpeater init Failed!\n");
            HAL_Delay(500);
        }
    }

    LOG_STR("\nRed stone line init over!\nStart running...\n");

    start_schedule(); // 开启调度
    
    /* infinite loop */
    while (1)
    {
        task_schedule();
    }
}

/**
  * @brief  System clock configuration function
  * @param  None
  * @retval None
  */
static void APP_SystemClockConfig(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /* Oscillator configuration */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE; /* Select oscillator HSE, HSI, LSI, LSE */
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;                           /* Enable HSI */
  RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;                           /* HSI 1 frequency division */
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_24MHz;  /* Configure HSI clock 24MHz */
  RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS_DISABLE;               /* Close HSE bypass */
  RCC_OscInitStruct.LSIState = RCC_LSI_OFF;                          /* Close LSI */
  /*RCC_OscInitStruct.LSICalibrationValue = RCC_LSICALIBRATION_32768Hz;*/
  RCC_OscInitStruct.LSEState = RCC_LSE_OFF;                          /* Close LSE */
  /*RCC_OscInitStruct.LSEDriver = RCC_LSEDRIVE_MEDIUM;*/
  /* Configure oscillator */
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    APP_ErrorHandler();
  }

  /* Clock source configuration */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1; /* Choose to configure clock HCLK, SYSCLK, PCLK1 */
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSISYS; /* Select HSISYS as the system clock */
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;        /* AHB clock 1 division */
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;         /* APB clock 1 division */
  /* Configure clock source */
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    APP_ErrorHandler();
  }
}

/**
  * @brief  Error executing function.
  * @param  None
  * @retval None
  */
void APP_ErrorHandler(void)
{
  while (1)
  {
  }
}

void myADC_init(void){
    __HAL_RCC_ADC_CLK_ENABLE();                                                /* 使能 ADC 时钟 */

    /* 初始化 ADC */
    ADC_ChannelConfTypeDef        sConfig;
    
    hadc.Instance = ADC1;
    
    hadc.Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV16;               /* 设置adc时钟*/
    hadc.Init.Resolution            = ADC_RESOLUTION_12B;                      /* 12位 转换模式 */
    hadc.Init.DataAlign             = ADC_DATAALIGN_RIGHT;                     /* 数据右对齐 */
    hadc.Init.ScanConvMode          = ADC_SCAN_DIRECTION_FORWARD;              /* 顺序扫描*/
    hadc.Init.EOCSelection          = ADC_EOC_SINGLE_CONV;                     /* 单次转换 */
    hadc.Init.LowPowerAutoWait      = DISABLE;                                 /* 自动延迟转换功能禁用 */
    hadc.Init.ContinuousConvMode    = DISABLE;                                 /* 禁用连续模式 */
    hadc.Init.DiscontinuousConvMode = DISABLE;                                 /* 禁用不连续模式 */
    hadc.Init.ExternalTrigConv      = ADC_SOFTWARE_START;                      /* 软件触发 */
    hadc.Init.ExternalTrigConvEdge  = ADC_EXTERNALTRIGCONVEDGE_NONE;           /* 软件触发时，该参数无效 */
    hadc.Init.Overrun               = ADC_OVR_DATA_OVERWRITTEN;                /* 在溢出的情况下，DR寄存器被最后一次转换结果覆盖 */
    hadc.Init.SamplingTimeCommon    = ADC_SAMPLETIME_239CYCLES_5;              /* 通道采样时间 */
    HAL_ADC_Init(&hadc);
    
    // 左侧锁存信号检测
    sConfig.Rank         = ADC_RANK_CHANNEL_NUMBER;
    sConfig.Channel      = ADC_CHANNEL_1;
    HAL_ADC_ConfigChannel(&hadc, &sConfig);
    
    // 红石信号输入检测
    sConfig.Rank         = ADC_RANK_CHANNEL_NUMBER;
    sConfig.Channel      = ADC_CHANNEL_2;
    HAL_ADC_ConfigChannel(&hadc, &sConfig);
    
    // 右侧锁存信号检测
    sConfig.Rank         = ADC_RANK_CHANNEL_NUMBER;
    sConfig.Channel      = ADC_CHANNEL_3;
    HAL_ADC_ConfigChannel(&hadc, &sConfig);

    // 内部温度传感器通道
    sConfig.Rank         = ADC_RANK_CHANNEL_NUMBER;
    sConfig.Channel      = ADC_CHANNEL_TEMPSENSOR;
    HAL_ADC_ConfigChannel(&hadc, &sConfig);

    // 内部参考电压通道
    sConfig.Rank         = ADC_RANK_CHANNEL_NUMBER;
    sConfig.Channel      = ADC_CHANNEL_VREFINT;
    HAL_ADC_ConfigChannel(&hadc, &sConfig);
    
    // 使用内部 1.5V 参考电压
    HAL_ADC_ConfigVrefBuf(&hadc, ADC_VREFBUF_1P5V);

    HAL_ADCEx_Calibration_Start(&hadc);

    // HAL_ADC_Start_IT(&hadc);
}

/**
  * @brief  ADC转换完成中断回调服务函数
  * @param  None
  * @retval None
  */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    static uint8_t x = 0;
    
    ADC_converted_data[x++] = hadc->Instance->DR;
    
    if(x == 5)
    {
        x = 0;
        flag_conversion_complete = 1;
    }
}


#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* Users can add their own printing information as needed,
     for example: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* Infinite loop */
  while (1)
  {
  }
}
#endif /* USE_FULL_ASSERT */

/************************ (C) COPYRIGHT Puya *****END OF FILE******************/
